package com.lb.uts.quartz;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.lb.uts.constants.UTSConstants;
import com.lb.uts.entity.JobExecuteRecord;
import com.lb.uts.entity.ScheduleJob;
import com.lb.uts.entity.WaitJob;
import com.lb.uts.mapper.ActiveClientMapper;
import com.lb.uts.service.IJobRecordService;
import com.lb.uts.service.IScheduleJobService;
import com.lb.uts.service.manager.DependManager;
import com.lb.uts.service.policy.DefaultJobExecute;
import com.lb.uts.util.PolicyUtil;
import com.lb.uts.util.SpringContextUtil;
import com.lb.uts.service.manager.ModifyManager;
import com.lb.uts.service.manager.SchedulerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

/**
 * 从DB中初始化Job，在Spring容器启动后，自动运行
 *
 * @author liangb
 * 此处采用定时任务的方式进行刷新
 * 1、效率低下，有效的更新次数太少
 * 2、占用内存
 * <p>
 * 优化方向：使用观察者模式设计，这段逻辑，但是要考虑多线程问题
 */
@Service
public class InitDBJob implements ApplicationListener<ContextRefreshedEvent> {
    private static final Logger logger = LoggerFactory.getLogger(InitDBJob.class);

    @Autowired
    private SchedulerManager manager;
    @Autowired
    private ActiveClientMapper activeClientMapper;

    @Autowired
    private IScheduleJobService scheduleJobService;

    @Autowired
    private IJobRecordService jobRecordService;

    @Value("${thread.sleep.time.base}")
    private String sleepTimeBase;

    @Value("${refresh.thread.time.times}")
    private String refreshTimeTimes;

    /**
     * 在web 项目中（spring mvc），系统会存在两个容器，一个是root application context,
     * 另一个就是我们自己的 projectName-servlet  context（作为root application context的子容器）。
     * <p>
     * 这种情况下，就会造成onApplicationEvent方法被执行两次。
     * 为了避免上面提到的问题，我们可以只在root application context初始化完成后调用逻辑代码，其他的容器的初始化完成，则不做任何处理
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {

        if (event.getApplicationContext().getParent() == null) {
            manager.initDBJob();
            //初始化job的客户端信息
            List<Map<String, String>> ipsStringMap = activeClientMapper.groupBySystemName();
            PolicyUtil.initJobIpList(ipsStringMap);
            //定时刷新任务
            new Thread() {
                public void run() {
                    int time = 0;
                    while (true) {
                        try {
                            //开始执行任务
                            Object obj = null;
                            while (true) {
                                obj = ModifyManager.get(0, Integer.valueOf(sleepTimeBase) * Integer.valueOf(refreshTimeTimes));
                                if (obj != null) {
                                    //开始刷新
                                    logger.info("定时任务开始刷新");
                                    List<Map<String, String>> ipsStringMap = activeClientMapper.groupBySystemName();
                                    PolicyUtil.updateJobIpList(ipsStringMap);
                                    PolicyUtil.updateJobList(scheduleJobService.selectUnDeleteList());
                                    time = 0;
                                    ModifyManager.remove(obj);
                                } else {
                                    time++;
                                    if (time % 100 == 0) {
                                        //连续100次没有获取刷新数据，主动刷新一次
                                        ModifyManager.add(1);
                                        time = 0;
                                    }
                                }
                            }
                        } catch (Exception e) {
                            logger.error("任务刷新异常==>", e);
                        }
                    }
                }
            }.start();
            new Thread() {
                public void run() {
                    while (true) {
                        try {
                            Iterator<WaitJob> waitJobs = DependManager.waitJobList.iterator();
                            for (; waitJobs.hasNext(); ) {
                                WaitJob waitJob = waitJobs.next();
                                //查看依赖运行
                                ScheduleJob scheduleJob = scheduleJobService.selectUniqeJob(waitJob.getJobName(), waitJob.getJobGroup());
                                if (scheduleJob.getRunNum() <= 0) {
                                    //更新执行记录
                                    JobExecuteRecord jobExecuteRecord = jobRecordService.getById(waitJob.getRecordId());
                                    jobExecuteRecord.setResponseContent("前置任务等待完毕，正在执行.....");
                                    jobRecordService.update(jobExecuteRecord);
                                    DefaultJobExecute.post(scheduleJob, waitJob.getRecordId(), waitJob.getHost(), -1, -1);
                                    waitJobs.remove();
                                } else {
                                    //验证是否超时
                                    if (waitJob.isTimeOut()) {
                                        waitJobs.remove();
                                        //更新任务状态
                                        SpringContextUtil.getBean(IJobRecordService.class).updateFailRecord(null, waitJob.getHost(), waitJob.getRecordId(), "等待前置任务:" + waitJob.getJobGroup() + "_" + waitJob.getJobName() + "执行超时");
                                    }
                                }
                            }
                            Thread.sleep(UTSConstants.WAIT_JOB_EXE_TIME);
                        } catch (Exception e) {
                            logger.error("任务刷新异常==>", e);
                        }
                    }
                }
            }.start();
        }
    }
}
